package top.songxs.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import top.songxs.gmall.cart.vo.UserAuthInfoVo;
import top.songxs.gmall.common.execption.GmallException;
import top.songxs.gmall.common.result.ResultCodeEnum;
import top.songxs.gmall.common.util.UserAuthUtil;
import top.songxs.gmall.feign.cart.CartRpcFeignClient;
import top.songxs.gmall.feign.product.SkuInfoFeignClient;
import top.songxs.gmall.feign.ware.WareManageFeignClient;
import top.songxs.gmall.order.dto.DetailDTO;
import top.songxs.gmall.order.dto.OrderSubmitDTO;
import top.songxs.gmall.order.entity.OrderDetail;
import top.songxs.gmall.order.entity.OrderInfo;
import top.songxs.gmall.order.entity.OrderStatusLog;
import top.songxs.gmall.order.enums.OrderStatus;
import top.songxs.gmall.order.enums.ProcessStatus;
import top.songxs.gmall.order.mapper.OrderInfoMapper;
import top.songxs.gmall.order.service.OrderDetailService;
import top.songxs.gmall.order.service.OrderInfoService;
import top.songxs.gmall.order.service.OrderStatusLogService;
import top.songxs.gmall.product.entity.SkuInfo;
import top.songxs.gmall.rabbit.constant.MqConstant;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 86176
 * @description 针对表【order_info(订单表 订单表)】的数据库操作Service实现
 * @createDate 2023-06-04 15:31:31
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo>
        implements OrderInfoService {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private SkuInfoFeignClient skuInfoFeignClient;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private CartRpcFeignClient cartRpcFeignClient;

    @Autowired
    private OrderStatusLogService orderStatusLogService;
    @Autowired
    private WareManageFeignClient wareManageFeignClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public String orderSubmit(OrderSubmitDTO orderSubmitDTO, String tradeNo) {

        String script = "if redis.call(\"EXISTS\",KEYS[1])\n" +
                "then\n" +
                "    return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end\n";
        //返回一个uuid
        Long executeResult = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList("order:confirm:" + tradeNo));

        if (executeResult == 0) {
            //不存在令牌
            throw new GmallException(ResultCodeEnum.REQ_REPEAT);
        }

        //对提交过来的购物项的价格进行校验，如果提交过来的购物项的价格是不一样的，则不允许进行提交

        List<DetailDTO> orderDetailList = orderSubmitDTO.getOrderDetailList();
        List<DetailDTO> resultList = orderDetailList.stream().filter(detailDTO -> {
            Long skuId = detailDTO.getSkuId();
            SkuInfo skuInfo = skuInfoFeignClient.getSkuInfo(skuId).getData();
            boolean flag = Objects.equals(skuInfo.getPrice(), detailDTO.getOrderPrice());
            return !flag;
        }).collect(Collectors.toList());
        orderDetailList.stream().forEach(detailDTO -> {
            String skuNum = detailDTO.getSkuNum() + "";
            String skuId = detailDTO.getSkuId() + "";

            HashMap<String, String> hashMap = new HashMap<>();
            hashMap.put("num", skuNum);
            hashMap.put("skuId", skuId);

            //远程调用一下库存系统
            ResponseEntity<String> result = wareManageFeignClient.hasStock(hashMap);
            String s = result.getBody();
            if ("0".equals(s)) {
                throw new GmallException(ResultCodeEnum.SECKILL_FINISH);
            }
        });

        if (resultList.size() > 0) {
            //价格存在变动
            throw new GmallException(ResultCodeEnum.SKU_PRICE_CHANGE);
        }
        //生成订单
        OrderInfo orderInfo = this.saveOrderInfo(tradeNo, orderSubmitDTO);

        //保存订单明细数据
        saveOrderDetail(orderInfo, orderSubmitDTO);

        //保存订单状态数据
        saveOrderStatusLog(orderInfo);

        //把redis中的选中的购物数据删除
        cartRpcFeignClient.deleteChecked();
        //开启一个延迟任务，完成订单超时未支付的功能，使用mq来模拟延迟队列
        Map<String, Long> hashMap = new HashMap<>();
        hashMap.put("orderId", orderInfo.getId());
        hashMap.put("userId", orderInfo.getUserId());
        String orderMsg = JSON.toJSONString(hashMap);
        rabbitTemplate.convertAndSend(MqConstant.ORDER_EXCHANGE_NAME, MqConstant.ORDER_MSG_ROUTING_KEY, orderMsg);
        return String.valueOf(orderInfo.getId());
    }

    @Override
    public void closeOrder(Long orderId, Long userId) {
        //关闭订单方法

        // 根据订单的id查询订单

        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getId, orderId);
        wrapper.eq(OrderInfo::getUserId, userId);
        OrderInfo orderInfo = this.getOne(wrapper);
        // 判断订单的状态是否为未支付，如果是修改订单的状态为已关闭
        String orderStatus = orderInfo.getOrderStatus();//订单装态
        String processStatus = orderInfo.getProcessStatus();//订单的处理状态

        if (orderStatus.equalsIgnoreCase(OrderStatus.UNPAID.name()) && processStatus.equalsIgnoreCase(ProcessStatus.UNPAID.name())) {
            // 判断订单的状态是否为未支付，如果是修改订单的状态为已关闭
            orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());

            // 为了保证修改没有问题，可以使用乐观锁
            wrapper.eq(OrderInfo::getOrderStatus, OrderStatus.UNPAID.toString());
            wrapper.eq(OrderInfo::getProcessStatus, ProcessStatus.UNPAID.toString());
            this.update(orderInfo, wrapper);

        }
    }

    @Override
    public Page<OrderInfo> pageOrderList(Long page, Long limit) {
        Page<OrderInfo> infoPage = new Page<>(page, limit);
        UserAuthInfoVo userAuthInfo = UserAuthUtil.getUserAuthInfo();
        String userId = userAuthInfo.getUserId();
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getUserId,userId);
        wrapper.eq(OrderInfo::getOrderStatus,OrderStatus.SPLIT.name());
        this.page(infoPage,wrapper);

        infoPage.getRecords().stream().forEach(orderInfo -> {
            Long orderId = orderInfo.getId();
            LambdaQueryWrapper<OrderDetail> orderDetailWrapper = new LambdaQueryWrapper<>();
            orderDetailWrapper.eq(OrderDetail::getOrderId,orderId);
            List<OrderDetail> list = orderDetailService.list(orderDetailWrapper);
            orderInfo.setOrderDetailList(list);
        });
        return infoPage;
    }


    private void saveOrderStatusLog(OrderInfo orderInfo) {


        // 构建订单状态对象
        OrderStatusLog orderStatusLog = new OrderStatusLog();
        orderStatusLog.setUserId(orderInfo.getUserId());
        orderStatusLog.setOrderId(orderInfo.getId());
        orderStatusLog.setOrderStatus(orderInfo.getOrderStatus());
        orderStatusLog.setOperateTime(new Date());

        // 保存数据
        orderStatusLogService.save(orderStatusLog);

    }

    private void saveOrderDetail(OrderInfo orderInfo, OrderSubmitDTO orderSubmitDTO) {

        List<DetailDTO> orderDetailList = orderSubmitDTO.getOrderDetailList();
        List<OrderDetail> orderDetails = orderDetailList.stream().map(detailDTO -> {
            OrderDetail orderDetail = new OrderDetail();

            orderDetail.setUserId(orderInfo.getUserId());
            orderDetail.setOrderId(orderInfo.getId());
            orderDetail.setSkuId(detailDTO.getSkuId());
            orderDetail.setSkuName(detailDTO.getSkuName());
            orderDetail.setImgUrl(detailDTO.getImgUrl());
            orderDetail.setOrderPrice(detailDTO.getOrderPrice());
            orderDetail.setSkuNum(detailDTO.getSkuNum());
            orderDetail.setCreateTime(new Date());
            // 实付金额
            orderDetail.setSplitTotalAmount(orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum())));

            orderDetail.setSplitActivityAmount(new BigDecimal("0"));
            orderDetail.setSplitCouponAmount(new BigDecimal("0"));

            return orderDetail;

        }).collect(Collectors.toList());

        this.orderDetailService.saveBatch(orderDetails);


    }

    private OrderInfo saveOrderInfo(String tradeNo, OrderSubmitDTO orderSubmitDTO) {

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setConsignee(orderSubmitDTO.getConsignee());
        orderInfo.setConsigneeTel(orderSubmitDTO.getConsigneeTel());

        // 订单总金额
        BigDecimal totalAmount = orderSubmitDTO.getOrderDetailList()
                .stream()
                .map(detailDTO -> detailDTO.getOrderPrice().multiply(new BigDecimal(detailDTO.getSkuNum())))
                .reduce(BigDecimal::add).get();
        orderInfo.setTotalAmount(totalAmount);

        // 订单状态: 给用户查看的
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());

        // 用户的id
        UserAuthInfoVo userAuthInfo = UserAuthUtil.getUserAuthInfo();
        orderInfo.setUserId(Long.parseLong(userAuthInfo.getUserId()));

        // 支付方式
        orderInfo.setPaymentWay(orderSubmitDTO.getPaymentWay());

        // 收货地址
        orderInfo.setDeliveryAddress(orderSubmitDTO.getDeliveryAddress());

        //  订单评论
        orderInfo.setOrderComment(orderSubmitDTO.getOrderComment());

        // 外部订单号
        orderInfo.setOutTradeNo(tradeNo);

        //订单体【默认用订单中第一个商品的名字即可】
        DetailDTO detailDTO = orderSubmitDTO.getOrderDetailList().get(0);
        orderInfo.setTradeBody(detailDTO.getSkuName());

        // 创建时间
        orderInfo.setCreateTime(new Date());

        // 过期时间
        long time = System.currentTimeMillis() + 30 * 60 * 1000;
        orderInfo.setExpireTime(new Date(time));

        // 订单的处理状态：一个订单状态对应多个处理状态，是一种更加详细的状态，给管理员查看
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());

        // 物流单号
        // orderInfo.setTrackingNo("");

        // 父订单id，后期进行拆单的时候使用
        // orderInfo.setParentOrderId(0L);

        // 使用第一个商品的图片作为订单图片
        orderInfo.setImgUrl(detailDTO.getImgUrl());

        // 操作时间
        orderInfo.setOperateTime(new Date());

        // 省id
        // orderInfo.setProvinceId(0L);

        // 优惠活动以及优惠券金额
        orderInfo.setActivityReduceAmount(new BigDecimal("0"));
        orderInfo.setCouponAmount(new BigDecimal("0"));

        // 原始金额
        orderInfo.setOriginalTotalAmount(totalAmount);

        // 运费
        orderInfo.setFeightFee(new BigDecimal("0"));

        // 可退款日期（签收后30天）
        // orderInfo.setRefundableTime(new Date());

        // 保存订单数据
        this.baseMapper.insert(orderInfo);

        // 返回订单数据
        return orderInfo;
    }
}




